package scatter.pay.rest.controller;

import cn.hutool.core.util.StrUtil;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import scatter.common.rest.controller.SuperController;
import scatter.common.rest.exception.BusinessException;
import scatter.common.rest.validation.DictService;
import scatter.order.pojo.constant.OrderConstants;
import scatter.order.pojo.param.UpdateOrderStatusParam;
import scatter.order.pojo.po.Order;
import scatter.order.rest.service.IOrderService;
import scatter.order.rest.service.IOrderStatusFrameworkService;
import scatter.order.rest.service.impl.OrderFrameworkHelperService;
import scatter.pay.pojo.form.WxPaySignForm;
import scatter.pay.rest.PayConfiguration;
import scatter.pay.rest.service.IPayService;
import scatter.pay.rest.third.WxPaySignHelper;

import javax.validation.Valid;

/**
 * <p>
 *
 * </p>
 *
 * @author yangwei
 * @since 2021-08-16 09:54
 */
@Slf4j
@Api(tags = "三方支付相关接口")
@RestController
@RequestMapping(PayConfiguration.CONTROLLER_BASE_PATH + "/pay")
public class PayThirdController  extends SuperController {
	@Autowired
	private IPayService iPayService;

	@Autowired
	private WxPaySignHelper wxPaySignHelper;

	@Autowired
	private WxPayService wxPayService;

	@Autowired
	private IOrderService iOrderService;
	@Autowired
	private OrderFrameworkHelperService orderFrameworkHelperService;

	@Autowired
	private DictService dictService;


	/**
	 * 微信支付通知，主要用于有appcode场景
	 * appcode主要是用于支付多个公众号或小程序
	 * @param xml
	 * @return
	 */
	@ApiOperation("微信支付通知")
	@PostMapping(value = "/wx/pay/notify/{appCode}", produces = {"application/xml;charset=UTF-8"})
	@ResponseStatus(HttpStatus.OK)
	public String wxPayNotifyWithAppCode(@RequestBody String xml, @PathVariable String appCode){
		return wxPayNotifyHandle(xml,appCode);

	}

	/**
	 * 微信支付通知，主要用于没有appcode场景
	 * @return
	 */
	@ApiOperation("微信支付通知")
	@PostMapping(value = "/wx/pay/notify",produces = {"application/xml;charset=UTF-8"})
	@ResponseStatus(HttpStatus.OK)
	public String wxPayNotifyWithoutAppCode(@RequestBody String xml){
		return wxPayNotifyHandle(xml,null);
	}

	/**
	 * 支付通知结果处理
	 * @param xml
	 * @param appCode
	 * @return
	 */
	private String wxPayNotifyHandle(String xml,String appCode){
		if (!isStrEmpty(appCode)) {
			wxPayService.switchover(appCode);

		}
		WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
		try {
			wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xml);
			log.info("微信支付通知结果={}",toJsonStr(wxPayOrderNotifyResult));

		} catch (WxPayException e) {
			log.error("处理微信支付通知异常",e);
			return WxPayNotifyResponse.fail(e.getMessage());
		}
		// 修改订单状态为已支付
		String outTradeNo = wxPayOrderNotifyResult.getOutTradeNo();
		Order byOrderNo = iOrderService.getByOrderNo(outTradeNo);
		if (byOrderNo == null) {
			log.error("微信支付通知结果处理，订单号不存在,outTradeNo={}",outTradeNo);
			return WxPayNotifyResponse.fail("订单号不存在");

		}
		String categoryDictValue = dictService.getValueById(byOrderNo.getCategoryDictId());

		IOrderStatusFrameworkService iOrderStatusFrameworkService = orderFrameworkHelperService.getIOrderStatusFrameworkService(byOrderNo.getChannelCode(), categoryDictValue);
		UpdateOrderStatusParam updateOrderStatusParam = new UpdateOrderStatusParam();
		updateOrderStatusParam.setOrderNo(outTradeNo);
		updateOrderStatusParam.setStatus(OrderConstants.OrderStatusItem.paid.itemValue());
		updateOrderStatusParam.setChannel(byOrderNo.getChannelCode());
		updateOrderStatusParam.setCategoryDictValue(categoryDictValue);
		/**
		 * 添加支付结果，用于生成流水 key=wxPayOrderNotifyResult 使用在 DefaultThirdPayOrderStatusFrameworkServiceImpl 生成流水
		 */
		updateOrderStatusParam.addExt("wxPayOrderNotifyResult",wxPayOrderNotifyResult);


		boolean b = iOrderStatusFrameworkService.updateOrderStatus(updateOrderStatusParam);
		if (!b) {
			log.error("订单状态服务处理失败",outTradeNo);
			return WxPayNotifyResponse.fail("订单状态服务处理失败");

		}

		return WxPayNotifyResponse.success("处理成功");

	}


	/**
	 * 当前用于jsapi调起支付时签名使用
	 * @param signForm
	 * @return
	 */
	@ApiOperation("微信支付签名")
	@GetMapping(value = "/wx/paySign")
	@ResponseStatus(HttpStatus.OK)
	public Object wxPaySign(@Valid WxPaySignForm signForm) {
		if (StrUtil.isAllEmpty(signForm.getOrderNo(),signForm.getPrepayId())) {
			throw new BusinessException("订单号和预支付id至少传一个");
		}
		return wxPaySignHelper.paySign(signForm);
	}


	/**
	 * 微信退款通知，主要用于有appcode场景
	 * appcode主要是用于退款多个公众号或小程序
	 * @param xml
	 * @return
	 */
	@ApiOperation("微信退款通知")
	@PostMapping(value = "/wx/refund/notify/{appCode}", produces = {"application/xml;charset=UTF-8"})
	@ResponseStatus(HttpStatus.OK)
	public String wxRefundNotifyWithAppCode(@RequestBody String xml,@PathVariable String appCode){
		return wxRefundNotify(xml,appCode);
	}

	/**
	 * 微信退款通知，主要用于没有appcode场景
	 * @return
	 */
	@ApiOperation("微信退款通知")
	@PostMapping(value = "/wx/refund/notify",produces = {"application/xml;charset=UTF-8"})
	@ResponseStatus(HttpStatus.OK)
	public String wxRefundNotifyWithoutAppCode(@RequestBody String xml){
		return wxRefundNotify(xml,null);
	}


	/**
	 * 微信退款通知处理
	 * @param xml
	 * @param appCode
	 * @return
	 */
	private String wxRefundNotify(String xml,String appCode){
		if (!isStrEmpty(appCode)) {
			wxPayService.switchover(appCode);
		}
		WxPayRefundNotifyResult wxPayRefundNotifyResult = null;
		try {
			wxPayRefundNotifyResult = wxPayService.parseRefundNotifyResult(xml);
			log.info("微信退款通知结果={}",toJsonStr(wxPayRefundNotifyResult));

		} catch (WxPayException e) {
			log.error("处理微信退款通知异常",e);
			return WxPayNotifyResponse.fail(e.getMessage());
		}
		if (!"SUCCESS".equals(wxPayRefundNotifyResult.getReqInfo().getRefundStatus())) {
			// 暂不处理
			log.warn("微信退款通知,暂时只处理退款成功状态");
			return WxPayNotifyResponse.success("处理成功");
		}
		// 修改订单状态为已退款
		String outTradeNo = wxPayRefundNotifyResult.getReqInfo().getOutTradeNo();
		String outRefundNo = wxPayRefundNotifyResult.getReqInfo().getOutRefundNo();
		Order byOrderNo = iOrderService.getByOrderNo(outTradeNo);
		if (byOrderNo == null) {
			log.error("微信退款通知结果处理，订单号不存在,outTradeNo={}",outTradeNo);
			return WxPayNotifyResponse.fail("订单号不存在");

		}
		String categoryDictValue = dictService.getValueById(byOrderNo.getCategoryDictId());


		IOrderStatusFrameworkService iOrderStatusFrameworkService = orderFrameworkHelperService.getIOrderStatusFrameworkService(byOrderNo.getChannelCode(), categoryDictValue);
		UpdateOrderStatusParam updateOrderStatusParam = new UpdateOrderStatusParam();
		updateOrderStatusParam.setOrderNo(outTradeNo);
		updateOrderStatusParam.setStatus(OrderConstants.OrderStatusItem.refund.itemValue());
		updateOrderStatusParam.setChannel(byOrderNo.getChannelCode());
		updateOrderStatusParam.setCategoryDictValue(categoryDictValue);
		updateOrderStatusParam.setOrderRefundNo(outRefundNo);
		updateOrderStatusParam.addExt("wxPayRefundNotifyResult",wxPayRefundNotifyResult);

		boolean b = iOrderStatusFrameworkService.updateOrderStatus(updateOrderStatusParam);
		if (!b) {
			log.error("订单状态服务处理失败",outTradeNo);
			return WxPayNotifyResponse.fail("订单状态服务处理失败");

		}

		return WxPayNotifyResponse.success("处理成功");

	}
}
